use std::sync::Arc;
use std::panic::{AssertUnwindSafe};
use axum::{
    extract::{Request},
    http::{self, StatusCode},
    middleware::Next,
    response::Response,
};
use common::{
    utils::auth_utils::get_user,
};
use futures::FutureExt;

/**
 * 拦截器白名单
 */
const EXCLOUD_PATH: &[&str] = &["/api/v1/user/err", "/api/v1/user/login"];

pub async fn auth(mut req: Request, next: Next) -> Result<Response, StatusCode> {
    let path = req.uri().path();
    if is_exclude_path(&path) {
        return Ok(next.run(req).await);
    }
    let auth_header = req
        .headers()
        .get(http::header::AUTHORIZATION)
        .and_then(|h| h.to_str().ok())
        .ok_or(StatusCode::UNAUTHORIZED)?;

    // 获取用户信息
    if let Some(user) = get_user(auth_header).await{
        req.extensions_mut().insert(Arc::new(user));
        Ok(next.run(req).await)
    }else {
        Err(StatusCode::UNAUTHORIZED)
    }
}

fn is_exclude_path(path: &str) -> bool {
    EXCLOUD_PATH.iter().any(|&p| p == path)
}

/**
 * 全局异常捕获处理
 */
pub async fn painc(req: Request, next: Next) -> Result<Response, StatusCode> {
    // 捕获异步异常
    let future = AssertUnwindSafe(next.run(req));
    match future.catch_unwind().await {
        Ok(response) => {
            // 正常情况，等待响应
            Ok(response)
        }
        Err(_) => {
            // error!("全局异常捕获: {:?}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}
